package com.example.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.common.Result;
import com.example.common.ResultUtil;
import com.example.common.exception.BusinessRuntimeException;
import com.example.entity.ProcessInstanceCreateRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.engine.IdentityService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceBuilder;
import org.flowable.engine.runtime.ProcessInstanceQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;


/**
 * @Description: 流程实例
 */
@RestController
@RequestMapping("runtime/process-instances")
@Slf4j
public class InstanceController {

    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private IdentityService identityService;


    /**
    * 功能描述: 启动：提交一个申请单
     *   启动流程实例(提交一个申请单)，实例启动成功，返回当前活动任务
    * @author: 庞留杰
    * @exception
    * @date: 2020/9/11 9:17
    */
    @PostMapping
    public Result startByKey(@RequestBody ProcessInstanceCreateRequest request) {
        Assert.notNull(request.getBusinessKey(), "请输入业务id"); //act_re_procdef 中：level001:2:05d13bd4-f0fa-11ea-b26d-405bd8b55521
        Assert.notNull(request.getBusinessType(), "请输入业务类型");

        int paramsSet = ((request.getProcessDefinitionId() != null) ? 1 : 0) + ((request.getProcessDefinitionKey() != null) ? 1 : 0);
        if (paramsSet > 1) {
            throw new BusinessRuntimeException("processDefinitionId、processDefinitionKey或message中只能设置一个。");
        }
        // 获取流程构造器
        ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder();
        if(StringUtils.isNotBlank(request.getProcessDefinitionId())){
            processInstanceBuilder.processDefinitionId(request.getProcessDefinitionId());
        }
        if(StringUtils.isNotBlank(request.getProcessDefinitionKey())){
            processInstanceBuilder.processDefinitionKey(request.getProcessDefinitionKey());
        }
        if(StringUtils.isNotBlank(request.getBusinessKey())){
            processInstanceBuilder.businessKey(request.getBusinessKey());
        }
        if(StringUtils.isNotBlank(request.getBusinessName())){
            processInstanceBuilder.name(request.getBusinessName());
        }
        if(StringUtils.isNotBlank(request.getTenantId())){
            processInstanceBuilder.tenantId(request.getTenantId());
        }

        Map<String, Object> variables = request.getVariables();
        //测试跳过审核
        //通过设置流程变量_FLOWABLE_SKIP_EXPRESSION_ENABLED为true启动skipExpression属性,
        //必须是true而非字符串"true",若不启动是不生效的
//        variables.put("_FLOWABLE_SKIP_EXPRESSION_ENABLED",true);


        // 设置参数
        processInstanceBuilder.variables(variables);
        // setAuthenticatedUserId(UserUtils.getLoginUser().getUsername());
        //todo  userId
        identityService.setAuthenticatedUserId("我是当前登录的用户ID");

        ProcessInstance pi = null;
        try{
            // 启动（即创建）流程实例
            ProcessInstance processInstance = processInstanceBuilder.start();
            pi = processInstance;
            log.info("发起流程成功，流程ID:{}",processInstance.getId());
        }catch (FlowableObjectNotFoundException e){
            return new ResultUtil<>().setErrorMsg("启动流程失败，流程尚未发布成功");
        }
        //通过processInstance.getId() 可以判断流程是否发起成功
        return new ResultUtil<>().setSuccessMsg("启动流程实例："+pi.getId()+"，成功");
    }


    //查询  act_ru_execution 中的内容
    //分页查询流程实例
    @GetMapping
    public Result page(@RequestParam Map map,Page page){
        //map中包含两个字段 businessKey，name
       // actInstanceService.findPage(processInstanceDTO,page)
        int firstResult = (int)((page.getCurrent()-1)*page.getSize());
        int maxResults = (int)(page.getCurrent()*page.getSize());
        ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery();
        if(StringUtils.isNotBlank(map.get("businessKey")+"")){
            query.processInstanceBusinessKey(map.get("businessKey")+"");
        }
        if(StringUtils.isNotBlank(map.get("name")+"")){
            query.processInstanceNameLike(map.get("name")+"");
        }
        long count = query.count();
        List<ProcessInstance> processInstanceList = query.orderByStartTime().desc().listPage(firstResult,maxResults);
//        List<ProcessInstanceVo> processInstanceVos = BeanCopyUtil.copyListProperties(processInstanceList, ProcessInstanceVo::new);

        JSONArray arr = new JSONArray();
        for (ProcessInstance processInstance : processInstanceList) {
            JSONObject obj = new JSONObject();
            //自能查出ID
            obj.put("processInstanceId",processInstance.getId());
            obj.put("name",processInstance.getName());
            obj.put("businessKey",processInstance.getBusinessKey());
            obj.put("startTime",processInstance.getStartTime());
            obj.put("startUserId",processInstance.getStartUserId());

            obj.put("processDefinitionId",processInstance.getProcessDefinitionId());
            obj.put("processDefinitionKey",processInstance.getProcessDefinitionKey());
            obj.put("processDefinitionName",processInstance.getProcessDefinitionName());
            //isSuspended 如果流程实例被挂起，则返回true  （1挂起，2激活） 【对应act_ru_execution：SUSPENSION_STATE_】
            obj.put("isSuspended", processInstance.isSuspended() == true ? 1 : 2);
            //流程是否结束  【对应act_ru_execution：IS_CONCURRENT_】
            obj.put("isEnded", processInstance.isEnded());

            System.out.println("执行实例ID:" + processInstance.getId());
            System.out.println("流程定义ID:" + processInstance.getProcessDefinitionId());
            System.out.println("流程实例ID:" + processInstance.getProcessInstanceId());
            System.out.println("########################");


//            obj.put("processInstanceName",processInstance.getName());//null
            arr.add(obj);
        }
        page.setRecords(arr);
        page.setTotal(count);
        return new ResultUtil<>().setData(page);
    }


   //挂起、激活
    @GetMapping(value = "/{processInstanceId}/{action}")
    //suspend: 挂起流程,activate: 激活流程
    //action:任务类型 （1挂起，2激活）    processInstanceId: 流程实例ID
    public Result actionById(@PathVariable("processInstanceId") String processInstanceId, @PathVariable("action") String action) {
        if("1".equals(action)){
            try {
                //挂起流程
                runtimeService.suspendProcessInstanceById(processInstanceId);
            }catch (FlowableObjectNotFoundException e){
                throw new BusinessRuntimeException("通过ProcessInstanceId："+processInstanceId+"找不到流程实例");
            }catch (FlowableException e){
                throw new BusinessRuntimeException("流程实例"+processInstanceId+"已经处于挂起状态");
            }
            return new ResultUtil<>().setSuccessMsg("挂起成功");
        }else {
            try {
                //激活流程
                runtimeService.activateProcessInstanceById(processInstanceId);
            }catch (FlowableObjectNotFoundException e){
                throw new BusinessRuntimeException("通过ProcessInstanceId："+processInstanceId+"找不到流程实例");
            }catch (FlowableException e){
                throw new BusinessRuntimeException("流程实例"+processInstanceId+"已经处于激活状态");
            }
            return new ResultUtil<>().setSuccessMsg("激活成功");
        }
    }



//    @GetMapping(value = "/{processInstanceId}")
//    @ApiOperation(value = "查询", produces = "application/json")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "processInstanceId", value = "流程实例ID", required = true, dataType = "String")
//    })
//    public ApiResponse get(@PathVariable String processInstanceId){
//        Map<String,Object> objectMap = BeanUtil.beanToMap(actInstanceService.processInstanceId(processInstanceId));
//        return success(objectMap);
//    }
//
//    @PutMapping(value = "/{processInstanceId}/{action}")
//    @ApiOperation(value = "操作流程", notes = "suspend: 挂起流程,activate: 激活流程", produces = "application/json")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "action", value = "任务类型", required = true, dataType = "String"),
//            @ApiImplicitParam(name = "processInstanceId", value = "流程实例ID", required = true, dataType = "String")
//    })
//    public ApiResponse actionById(@PathVariable("processInstanceId") String processInstanceId, @PathVariable("action") String action) {
//        actInstanceService.action(action, processInstanceId);
//        return success(ActionEnum.actionOf(action).getName());
//    }
//
//    @DeleteMapping(value = "/{processInstanceId}")
//    @ApiOperation(value = "删除", notes = "删除流程", produces = "application/json")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "processInstanceId", value = "流程实例ID", required = true, dataType = "String")
//    })
//    public ApiResponse delete(@PathVariable String processInstanceId){
//        actInstanceService.deleteProcessInstance(processInstanceId,null);
//        return success("删除成功");
//    }
//
//    @ApiOperation(value = "获取人员", notes = "参与流程实例的人员信息", produces = "application/json")
//    @GetMapping(value = "/{processInstanceId}/identitylinks", produces = "application/json")
//    public ApiResponse getIdentityLinks(@PathVariable String processInstanceId){
//        return success(actInstanceService.getIdentityLinks(processInstanceId));
//    }
//
//    @PostMapping(value = "/{processInstanceId}/identitylinks")
//    @ApiOperation(value = "多实例加签", notes = "数据变化：act_ru_task、act_ru_identitylink各生成一条记录", produces = "application/json")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "activityDefId", value = "流程环节定义ID", required = true),
//            @ApiImplicitParam(name = "instanceId", value = "流程实例ID", required = true)
//    })
//    public ApiResponse addMultiInstanceExecution(@PathVariable String processInstanceId, @RequestParam("activityDefId") String activityDefId, @RequestBody Map<String, Object> variables) {
//        actInstanceService.addMultiInstanceExecution(activityDefId, processInstanceId, variables);
//        return success("加签成功");
//    }
//
//    @DeleteMapping(value = "/{currentChildExecutionId}/identitylinks")
//    @ApiOperation(value = "多实例减签", notes = "数据变化：act_ru_task减1、act_ru_identitylink不变", produces = "application/json")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "currentChildExecutionId", value = "子执行流ID", required = true, dataType = "String"),
//            @ApiImplicitParam(name = "flag", value = "子执行流是否已执行", required = true, dataType = "boolean")
//    })
//    public ApiResponse deleteMultiInstanceExecution(@PathVariable String currentChildExecutionId, boolean flag) {
//        actInstanceService.deleteMultiInstanceExecution(currentChildExecutionId, flag);
//        return success("减签成功");
//    }

}
